package similarity;

import java.util.Random;

import randomwalk.Submatrix;

public class LshHashFunction {
	
	private double[] multiplier;
	private double offset;
	private double bucketWidth; 
	
	public LshHashFunction(double bucketWidth, int vectorLength) {
		this.bucketWidth = bucketWidth;
		multiplier = generateRandomGaussianVector(vectorLength);
		offset = generateOffset(bucketWidth);
	}
	
	public static double[] generateRandomGaussianVector(int length) {
		double[] randomGaussianVector = new double [length];
		Random gaussianGen = new Random();
		
		for (int i = 0; i < length; i++) {
			randomGaussianVector[i] = gaussianGen.nextGaussian();
		}
		
		return randomGaussianVector;
	}
	
	//offset uniformly distributed between 0 and bucketWidth
	public static double generateOffset(double bucketWidth) {
		Random uniformGen = new Random();
		double offset = uniformGen.nextDouble();
		offset *= bucketWidth;
		
		return offset;
	}
	
	public int[] calculateUserHash(Submatrix submatrix, int resultLength) {
		double [] dotProductResult = new double [multiplier.length];
		submatrix.randomWalkTransition(multiplier, dotProductResult, -1);
		int [] hashResult = new int [multiplier.length];
		
		for(int i = 0; i < multiplier.length; i++) {
			hashResult[i] = (int) ((dotProductResult[i] + offset)/bucketWidth);
		}
	
		return hashResult;
	}

	@SuppressWarnings("unused")
	private void printMaxAndMinElem(double[] dotProductResult) {
		double max = 0.0;
		double min = 1.0;
		
		for (double d : dotProductResult) {
			if(d > max) {
				max = d;
			}
			if(d < min) {
				min = d;
			}
		}
		System.out.println("Max: " + max + " Min: " + min);
	}
}
